// NatTravClientTest.cpp : ¶¨Òå¿ØÖÆÌ¨Ó¦ÓÃ³ÌÐòµÄÈë¿Úµã¡£
// CLIENT ²âÊÔ³ÌÐò 

#include "trav_task.h"
#include <signal.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
//#include <windows.h>
//#pragma comment(lib , "ws2_32.lib")

// ########################## È«¾Öº¯ÊýÉùÃ÷ ###############################
int  InitSys();
void SigFunc(int v_sig);
//bool InitWinsock();
int  GetLocalIPAddress(unsigned long * pIp);
int  ParseCmd(string cmd);

CTravTask      g_trav_task;
OS::PTHREAD    g_pThread = 0;
bool           g_bRun = true;
CUdpEx *       g_pUdpEx=0;
int64          g_localID = 0;



#if __Win32__
uInt __stdcall RecvThread(void* param)
#else
void * RecvThread(void* param)
#endif
{
	uLong  srcIp; uShort srcPort;  // ¿Í»§¶ËÃüÁîÍ¨µÀÔÚNATÉÏµÄIPºÍPORT
	char buf[MAX_RECV_BUF];int bufLen;
	while( g_bRun )
	{
		// ½ÓÊÕÊý¾ÝÃüÁî¶Ë¿ÚµÄÊý¾Ý
		bufLen = sizeof(buf);memset(buf,0,sizeof(buf));

		if( g_pUdpEx->RecvUDPPacket(buf,&bufLen,&srcIp,&srcPort,4)==UDPEX_SUCCESS)
		{
			int ret = g_trav_task.HandlePacket(buf,bufLen,srcIp,srcPort);
		}
	}

	delete g_pUdpEx;
	g_pUdpEx=0;

	std::cout << "½áÊø ¼à¿ØÏß³Ì ·þÎñ£¡" << endl;
#if __Win32__
	return 0xFE0000E2;
#else
	return (void*)0;
#endif
}


int main(int argc, char* argv[])
{
	signal(SIGABRT,SigFunc);//°²×° Abnormal termination ²¶×½Æ÷
	signal(SIGTERM,SigFunc);//°²×° Termination ²¶×½Æ÷
	signal(SIGINT,SigFunc); //°²×° CTRL+C ²¶×½Æ÷
#if __Win32__
	if( !OS::InitWinsock() )
	{
		std::cout << "³õÊ¼»¯ WINSOCK Ê§°Ü£¡" << endl;
		return 0x00FF1133;
	}
	
#endif
	std::cout << "ÃüÁî¸ñÊ½ÈçÏÂ£º" << endl;
/*	std::cout << "1.        init/INIT" <<endl;
	std::cout << "          ³õÊ¼»¯Ä£¿é£¡ " << endl;
	std::cout << "¸ñÊ½£º    init -s StunServerIP -n NatServerIP -i HostID!" << endl;
	std::cout << "sample£º  init -s 172.16.5.14 -n 172.16.5.14 -i 111111!" << endl;
	std::cout << endl;*/
	std::cout << "2.        reg/REG "<<endl;
	std::cout << "          ×¢²á½Óµã" << endl;
	std::cout << "¸ñÊ½£º    reg -i localID" << endl;
	std::cout << "sample    reg -i 222222" << endl;
	std::cout << endl;
	std::cout << "3.        trav/TRAV "<<endl;
	std::cout << "          ÓëÄ¿µÄ½Óµã½øÐÐ´©Ô½£¡" << endl;
	std::cout << "¸ñÊ½£º    trav -d DestID" << endl;
	std::cout << "sample    trav -d 222222" << endl;
	std::cout << endl;
	std::cout << "4.        exit/EXIT/quit/QUIT "<< endl;
	std::cout << "          ÃüÁîÓÃÀ´ÍË³ö³ÌÐò" << endl;
	std::cout << "¸ñÊ½£º    quit  " << endl;
	std::cout << "sample    quit " << endl;
	std::cout << endl;
	std::cout << "ÇëÊäÈëÃüÁî£º"<< endl;

	g_pUdpEx = new CUdpEx();

	int s=0,ret = OS::CreateThread(&g_pThread,(OS::THREAD_ROUTINE)RecvThread,0); 
	if( ret != 0 )
	{
		std::cout << "´´½¨½ÓÊÜÊÕ¾ÝÏß³ÌÊ§°Ü£¡" << endl;
	}

	if( UDPEX_SUCCESS != (ret = g_pUdpEx->UdpSocket(&s,/*m_lLanIP*/0/* °ó¶¨µ½ËùÓÐIP*/,0)) )
	{
		std::cout<< "´ò¿ªÃüÁîÍ¨µÀÊ§°Ü£¨´´½¨SOCKETÊ§°Ü£©" << endl;
		delete g_pUdpEx;
		return ret;
	}

	g_trav_task.InitTask(g_pUdpEx,ntohl(inet_addr("172.16.5.14")),ntohl(inet_addr("172.16.5.14")),6100,5001);

	string cmd;
	while( g_bRun )
	{
		std::cin >> cmd;
		ParseCmd(cmd);
	}

	OS::TerminalThread( &g_pThread );

	return 0;
}

// ½âÎöÃüÁî
int ParseCmd(string cmd)
{
	string c1,v1,c2,v2,c3,v3;
	if( cmd == "exit" || cmd == "quit" || cmd == "EXIT" || cmd == "QUIT" )
	{
		g_bRun = false;
	}
	else if( cmd == "INIT" || cmd == "init" )
	{
		std::cin >> c1 >> v1 /*>> c2 >> v2 >> c3 >> v3*/;

		int64 id;string stun_ip="172.16.5.14",nat_ip="172.16.5.14";

		if( c1 == "-s"||c1 == "-S" ) { stun_ip=v1;}
		if( c2 == "-s"||c2 == "-S" ) { stun_ip=v2;}
		if( c3 == "-s"||c3 == "-S" ) { stun_ip=v3;}
		if( c1 == "-n"||c1 == "-N" ) { nat_ip=v1;}
		if( c2 == "-n"||c2 == "-N" ) { nat_ip=v2;}
		if( c3 == "-n"||c3 == "-N" ) { nat_ip=v3;}
		if( c1 == "-i"||c1 == "-I" ) { id= OS::atol64(v1.c_str());}
		if( c2 == "-i"||c2 == "-I" ) { id= OS::atol64(v2.c_str());}
		if( c3 == "-i"||c3 == "-I" ) { id= OS::atol64(v3.c_str());}

	}
	else if( cmd=="trav" || cmd=="TRAV")
	{
		unsigned short sp,dp; int64 did;
		std::cin >> c1 >> v1 ;
		if( c1 == "-d" ||c1 == "-D" ) { did=OS::atol64(v1.c_str());}

		g_trav_task.StartNatTrav(did,g_localID,222);

	}
	else if( cmd=="reg"||cmd=="REG" )
	{
		std::cin >> c1 >> v1 ;
		int64 id;
		if( c1 == "-i"||c1 == "-I" ) { id= OS::atol64(v1.c_str());}
		g_trav_task.RegTravClient(id,222);
		  g_localID = id;
	}
	else
	{
		std::cout << cmd << " Õâ¸öÃüÁî²»Ö§³Ö£¡" << endl;
	}

	return  1;
}

void SigFunc(int v_sig)
{
	g_bRun = false;

	printf("IN SigFunc()--->½ØÈ¡ÏµÍ³·¢ËÍ¹ýÀ´µÄ³ÌÐòÍË³öÐÅºÅ!\n");
	OS::Sleep(512);

	return;
}

/*
bool InitWinsock()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD( 2, 2 );

	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) 
	{                            
		return false;
	}

	if ( LOBYTE( wsaData.wVersion ) != 2 ||
		HIBYTE( wsaData.wVersion ) != 2 ) 
	{                       
		WSACleanup( );
		return false; 
	}

	return true;
}
*/
// this function can not work in linux!
int GetLocalIPAddress(unsigned long * pIp)
{
	struct hostent *phost;
	struct in_addr addr;
	char hostname[20];

	if(gethostname(hostname, 20) == 0)
	{
		if((phost=gethostbyname(hostname)) == NULL)
			return -58; 
        
		memcpy(&addr, phost->h_addr_list[0], sizeof(struct in_addr));
		*pIp = ntohl(addr.s_addr);

		return 1;
	}
	return -67;
}
